window.addEventListener("load",myOnLoadFunction);
window.addEventListener("keypress", keypressed, false);
var currentcell;
 

function test(){
	return 1;
}

function myOnLoadFunction(){
		currentcell = document.getElementById("solutionfield");
		currentcell.value = ""
}

function inverse(){
	currentcell.value = 1/currentcell.value
}

function sqrt(){
	currentcell.value = Math.sqrt(currentcell.value)
}

function setDefault(){
document.getElementById("solutionfield").value = ""
}

function backspace(){
	if(currentcell.value.length > 0){
		currentcell.value = currentcell.value.substring(0, currentcell.value.length-1)
	}
}


function keypressed(event){
	if(!(event.keyCode > 57 || event.keyCode < 48)){
		currentcell.value = currentcell.value + String(event.keyCode-48);
	}
	if(event.keyCode == 13){
		equals();
		return "equals";
	}
		
	if(event.keyCode == 106){
		currentcell.value = currentcell.value + String(event.keyCode);
	} // mult

	if(event.keyCode == 107){ // add
		currentcell.value = currentcell.value + String(event.keyCode);
	}
	if(event.keyCode == 109){ // sub
		currentcell.value = currentcell.value + String(event.keyCode);
	}
	if(event.keyCode == 110){ // decimal point
		currentcell.value = currentcell.value + String(event.keyCode);
	}
	if(event.keyCode == 111){ // div
		currentcell.value = currentcell.value + String(event.keyCode);
	}
}

function increase(cell){
	currentcell.value = currentcell.value + cell.value;
}


function equals(){
	num = eval(currentcell.value);
	fract = new Fraction(num);
	if(String(fract).length > 15)
		fract = getFraction(num);

	
	currentcell.value = String(fract)
}

Fraction = function(numerator, denominator)
{
    /* double argument invocation */
    if (numerator && denominator) {
        if (typeof(numerator) === 'number' && typeof(denominator) === 'number') {
            this.numerator = numerator;
            this.denominator = denominator;
        } else if (typeof(numerator) === 'string' && typeof(denominator) === 'string') {
            this.numerator = parseInt(numerator);
            this.denominator = parseInt(denominator);
        }
    /* single-argument invocation */
    } else if (!denominator) {
        num = numerator; // swap variable names for legibility
        if (typeof(num) === 'number') {  // just a straight number init
            this.numerator = num;
            this.denominator = 1;
        } else if (typeof(num) === 'string') {
            var a, b;  // hold the first and second part of the fraction, e.g. a = '1' and b = '2/3' in 1 2/3
                       // or a = '2/3' and b = undefined if we are just passed a single-part number
            a, b = num.split(' ');
            /* compound fraction e.g. 'A B/C' */
            //  if a is an integer ...
            if (a % 1 === 0 && b && b.match('/')) {
                return (new Fraction(a)).add(new Fraction(b));
            } else if (a && !b) {
                /* simple fraction e.g. 'A/B' */
                if (typeof(a) === 'string' && a.match('/')) {
                    // it's not a whole number... it's actually a fraction without a whole part written
                    var f = a.split('/');
                    this.numerator = f[0]; this.denominator = f[1];
                /* string floating point */
                } else if (typeof(a) === 'string' && a.match('\.')) {
                    return new Fraction(parseFloat(a));
                /* whole number e.g. 'A' */
                } else { // just passed a whole number as a string
                    this.numerator = parseInt(a);
                    this.denominator = 1;
                }
            } else {
                return undefined; // could not parse
            }
        }
    }
    this.normalize();
}


Fraction.prototype.clone = function()
{
    return new Fraction(this.numerator, this.denominator);
}


/* pretty-printer, converts fractions into whole numbers and fractions */
Fraction.prototype.toString = function()
{
    var wholepart = Math.floor(this.numerator / this.denominator);
    var numerator = this.numerator % this.denominator 
    var denominator = this.denominator;
    var result = [];
    if (wholepart != 0) 
        result.push(wholepart);
    if (numerator != 0)  
        result.push(numerator + '/' + denominator);
    return result.length > 0 ? result.join(' ') : 0;
}


/* destructively rescale the fraction by some integral factor */
Fraction.prototype.rescale = function(factor)
{
    this.numerator *= factor;
    this.denominator *= factor;
    return this;
}


Fraction.prototype.add = function(b)
{
    var a = this.clone();
    if (b instanceof Fraction) {
        b = b.clone();
    } else {
        b = new Fraction(b);
    }
    td = a.denominator;
    a.rescale(b.denominator);
    b.rescale(td);

    a.numerator += b.numerator;

    return a.normalize();
}


Fraction.prototype.subtract = function(b)
{
    var a = this.clone();
    if (b instanceof Fraction) {
        b = b.clone();  // we scale our argument destructively, so clone
    } else {
        b = new Fraction(b);
    }
    td = a.denominator;
    a.rescale(b.denominator);
    b.rescale(td);

    a.numerator -= b.numerator;

    return a.normalize();
}


Fraction.prototype.multiply = function(b)
{
    var a = this.clone();
    if (b instanceof Fraction)
    {
        a.numerator *= b.numerator;
        a.denominator *= b.denominator;
    } else if (typeof b === 'number') {
        a.numerator *= b;
    } else {
        return a.multiply(new Fraction(b));
    }
    return a.normalize();
}


Fraction.prototype.divide = function(b)
{
    var a = this.clone();
    if (b instanceof Fraction)
    {
        a.numerator /= b.numerator;
        a.denominator /= b.denominator;
    } else if (typeof b === 'number') {
        a.numerator /= b;
    } else {
        return a.divide(new Fraction(b));
    }
    return a.normalize();
}


Fraction.prototype.equals = function(b)
{
    if (!(b instanceof Fraction)) {
        b = new Fraction(b);
    }
    // fractions that are equal should have equal normalized forms
    var a = this.clone().normalize();
    var b = b.clone().normalize();
    return (a.numerator === b.numerator && a.denominator === b.denominator);
}


/* Utility functions */

/* Destructively normalize the fraction to its smallest representation. 
 * e.g. 4/16 -> 1/4, 14/28 -> 1/2, etc.
 * This is called after all math ops.
 */
Fraction.prototype.normalize = (function()
{

    var isFloat = function(n)
    {
        return (typeof(n) === 'number' && 
                ((n > 0 && n % 1 > 0 && n % 1 < 1) || 
                 (n < 0 && n % -1 < 0 && n % -1 > -1))
               );
    }

    var roundToPlaces = function(n, places) 
    {
        if (!places) {
            return Math.round(n);
        } else {
            var scalar = Math.pow(10, places);
            return Math.round(n*scalar)/scalar;
        }
    }
        
    return (function() {

        /* first check if we have decimals, and if we do eliminate them
         * multiply by the 10 ^ number of decimal places in the number
         * round the number to nine decimal places
         * to avoid js floating point funnies
         */
        if (isFloat(this.denominator)) {
            var rounded = roundToPlaces(this.denominator, 9);
            var scaleup = Math.pow(10, rounded.toString().split('.')[1].length);
            this.denominator = Math.round(this.denominator * scaleup); // this !!! should be a whole number
            //this.numerator *= scaleup;
            this.numerator *= scaleup;
        } 
        if (isFloat(this.numerator)) {
            var rounded = roundToPlaces(this.numerator, 9);
            var scaleup = Math.pow(10, rounded.toString().split('.')[1].length);
            this.numerator = Math.round(this.numerator * scaleup); // this !!! should be a whole number
            //this.numerator *= scaleup;
            this.denominator *= scaleup;
        }
        var gcf = Fraction.gcf(this.numerator, this.denominator);
        this.numerator /= gcf;
        this.denominator /= gcf;
        return this;
    });

})();


/* Takes two numbers and returns their greatest common factor.
 */
Fraction.gcf = function(a, b)
{

    var common_factors = [];
    var fa = Fraction.primeFactors(a);
    var fb = Fraction.primeFactors(b);
    // for each factor in fa
    // if it's also in fb
    // put it into the common factors
    fa.forEach(function (factor) 
    { 
        var i = fb.indexOf(factor);
        if (i >= 0) {
            common_factors.push(factor);
            fb.splice(i,1); // remove from fb
        }
    });

    if (common_factors.length === 0)
        return 1;

    var gcf = (function() {
        var r = common_factors[0];
        var i;
        for (i=1;i<common_factors.length;i++)
        {
            r = r * common_factors[i];
        }
        return r;
    })();

    return gcf;

};


Fraction.primeFactors = function(n) 
{

    var num = n;
    var factors = [];
    var _factor = 2;  // first potential prime factor

    while (_factor * _factor <= num)  // should we keep looking for factors?
    {      
      if (num % _factor === 0)  // this is a factor
        { 
            factors.push(_factor);  // so keep it
            num = num/_factor;  // and divide our search point by it
        }
        else
        {
            _factor++;  // and increment
        }
    }

    if (num != 1)                    // If there is anything left at the end...
    {                                // ...this must be the last prime factor
        factors.push(num);           //    so it too should be recorded
    }

    return factors;                  // Return the prime factors
}

function numRepeating(n, d) {
    var pFS = Fraction.primeFactors(d);
    var lenOutput = 0
    for (var i = 0; i < pFS.length; i++) { // Go through each of the denominators prime factors
	
        if (pFS[i] !== 2 && pFS[i] !== 5) { // We have a repeating decimal

            var output = new Array();
            var ns = new Array();
			
            // Let's find the repeating decimal
            // Repeating decimal algorithm - uses long division
            for (var i = 0; i < 20; i++) { // For now find 20 spots, ideally this should stop after it finds the repeating decimal
                // How many times does the denominator go into the numerator evenly
                var temp2 = parseInt(n / d);

                if (ns[n] === undefined) {
                    ns[n] = i;
                } else {
                	lenOutput = output.slice(ns[n]).join('').length
                	return lenOutput;
                    return "Repeating decimal: " + 
                        output.slice(0, 1).join('') +
                        '.' +
                        output.slice(1, ns[n]).join('') +
                        '[' + output.slice(ns[n]).join('') + ']';
                        lenOutput = output.slice(ns[n]).join('').length
                    
                }

                output.push(temp2);
                var n = n % d;
                n += "0";
            }           
            return "Repeating decimal: " + output;
            return lenOutput
        
    }

    // Terminating decimal
    return "Terminating decimal: " + n / d;
}
}

function getFraction(num){
	pow = findRepeat(num);
	if(pow == "error")
		return("error");
	tenPow = Math.pow(10, pow);
	numTenPow = num*tenPow;
	fracString = String(num);
	fracShort = Number(fracString.substring(0, fracString.length-(pow+1)));
	roundedFrac = (Math.round((numTenPow-num)*10000000))/10000000
	newFraction = new Fraction(roundedFrac, (tenPow-1));
	return newFraction;
		
	
}

function findRepeat(num)
{
	var number = String(num)
    var decimal = number.substring(number.indexOf('.') + 1, number.length-1 );
    var maxLength = decimal.length;
    for(var i = 0; i < maxLength; i++)
    {	
    	//single repetition
        if(maxLength> 11 && i < maxLength-9 && decimal.charAt(i+0) == decimal.charAt(i+1) && decimal.charAt(i+1) == decimal.charAt(i+2) 
        && decimal.charAt(i+2) == decimal.charAt(i+3) && decimal.charAt(i+3) == decimal.charAt(i+4) 
        && decimal.charAt(i+4) == decimal.charAt(i+5) && decimal.charAt(i+5) == decimal.charAt(i+6)) 
            return 1;
        //octuple repetition
        if(maxLength>15 && i < maxLength-15 && decimal.substring(i, i+8) == decimal.substring(i+8, i+16))
        	return 8;
        //septuple repetition
        if(maxLength> 13 && i < maxLength-13 && decimal.substring(i, i+7) == decimal.substring(i+7, i+14))
        	return 7;
        //sextuple repetition
        if(maxLength> 11 && i < maxLength-11 && decimal.substring(i, i+6) == decimal.substring(i+6, i+12))
        	return 6;
       	//quintiple repetition
       	if(maxLength> 9 && i < maxLength-9 && decimal.substring(i, i+5) == decimal.substring(i+5, i+10))
       		return 5;
       	//quadruple repetition
       	if(maxLength> 7 && i < maxLength-7 && decimal.substring(1, i+4) == decimal.substring(1+4, i+8))
       		return 4;
        //triple repetition
        if(maxLength> 5 && i < maxLength-5 && decimal.substring(1, i+3) == decimal.substring(1+3, i+6))
            return 3;
        //double repetition
        if(maxLength> 3 && i < maxLength-3 && decimal.substring(1, i+2) == decimal.substring(1+2, i+4))
            return 2;
    }

    return "error";
}















